/*
 * timer.cpp
 *
 *  Created on: 2024年7月16日
 *      Author: ZKSWE Develop Team
 */

#include "common.h"
#include "timer.h"
#include <algorithm>
#include <base/handler.hpp>

namespace misc {

struct STimerCell {
	int id;
	int run_time;
	int total_time;
	timer_cb cb;
	void *user_data;
};

static std::list<STimerCell> s_timer_list;
static Mutex s_list_lock;

static void on_message_handler(const base::message<void*> *msg, const void *user_data);
static base::handler<void*> s_timer_handler(on_message_handler, NULL);

static inline std::list<STimerCell>::iterator find_timer_cell(int id) {
	return std::find_if(s_timer_list.begin(), s_timer_list.end(),
							[id](const STimerCell &t) { return t.id == id; });
}

static inline void send_timer_message(const STimerCell &timer) {
	if (timer.run_time < timer.total_time) {
		s_timer_handler.send_unique_message_delayed(timer.id, (timer.run_time == -1) ? 0 : 1000);
	}
}

static inline void remove_timer_message(int id) {
	s_timer_handler.remove_messages(id);
}

static void on_message_handler(const base::message<void*> *msg, const void *user_data) {
	STimerCell timer;

	{
		Mutex::Autolock _l(s_list_lock);

		auto it = find_timer_cell(msg->what);
		if (it == s_timer_list.end()) {
			return;
		}

		it->run_time++;
		timer = *it;

		if (timer.run_time >= timer.total_time) {
			s_timer_list.erase(it);
		}
	}

	if (timer.cb) {
		timer.cb(timer.id, timer.run_time, timer.total_time, timer.user_data);
	}

	send_timer_message(timer);
}

void start_timer(int id, int time, timer_cb cb, void *user_data) {
	LOGD("[timer] %s id %d, time %d\n", __FUNCTION__, id, time);
	Mutex::Autolock _l(s_list_lock);

	if (find_timer_cell(id) != s_timer_list.end()) {
		LOGE("[timer] id %d is started\n", id);
		return;
	}

	STimerCell timer = { id, -1, time, cb, user_data };
	s_timer_list.push_back(timer);
	send_timer_message(timer);
}

void stop_timer(int id) {
	LOGD("[timer] %s id %d\n", __FUNCTION__, id);
	Mutex::Autolock _l(s_list_lock);

	auto it = find_timer_cell(id);
	if (it != s_timer_list.end()) {
		s_timer_list.erase(it);
	}

	remove_timer_message(id);
}

void reset_timer(int id, int time) {
	LOGD("[timer] %s id %d\n", __FUNCTION__, id);
	Mutex::Autolock _l(s_list_lock);

	auto it = find_timer_cell(id);
	if (it == s_timer_list.end()) {
		LOGE("[timer] not find id %d\n", id);
		return;
	}

	it->run_time = 0;
	it->total_time = time;
	send_timer_message(*it);
}

void pause_timer(int id) {
	LOGD("[timer] %s id %d\n", __FUNCTION__, id);
	remove_timer_message(id);
}

void resume_timer(int id) {
	LOGD("[timer] %s id %d\n", __FUNCTION__, id);
	Mutex::Autolock _l(s_list_lock);

	auto it = find_timer_cell(id);
	if (it == s_timer_list.end()) {
		LOGE("[timer] not find id %d\n", id);
		return;
	}

	send_timer_message(*it);
}

bool is_timer_running(int id) {
	Mutex::Autolock _l(s_list_lock);
	
	return find_timer_cell(id) != s_timer_list.end();
}

}
